home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / Macintosh Sample Code / SC.001.Sample / Sample.a < prev    next >
Encoding:
Text File  |  1989-05-31  |  38.3 KB  |  992 lines  |  [TEXT/MPS ]

  1. *
  2. *    Apple Macintosh Developer Technical Support
  3. *
  4. *    MultiFinder-Aware Simple Sample Application
  5. *
  6. *    Sample
  7. *
  8. *    Sample.a    -    Assembler Source
  9. *
  10. *    Copyright © 1989 Apple Computer, Inc.
  11. *    All rights reserved.
  12. *
  13. *    Versions:    
  14. *        1.00            08/88
  15. *        1.01            11/88
  16. *        1.02            04/89
  17. *        1.03            06/89
  18. *
  19. *    Components:
  20. *        Sample.p        June 1, 1989
  21. *        Sample.c        June 1, 1989
  22. *        Sample.a        June 1, 1989
  23. *        Sample.inc1.a        June 1, 1989
  24. *        SampleMisc.a        June 1, 1989
  25. *        Sample.r        June 1, 1989
  26. *        Sample.h        June 1, 1989
  27. *        PSample.make        June 1, 1989
  28. *        CSample.make        June 1, 1989
  29. *        ASample.make        June 1, 1989
  30. *
  31. *    Sample is an example application that demonstrates how to
  32. *    initialize the commonly used toolbox managers, operate 
  33. *    successfully under MultiFinder, handle desk accessories, 
  34. *    and create, grow, and zoom windows.
  35. *
  36. *    It does not by any means demonstrate all the techniques 
  37. *    you need for a large application. In particular, Sample 
  38. *    does not cover exception handling, multiple windows/documents, 
  39. *    sophisticated memory management, printing, or undo. All of 
  40. *    these are vital parts of a normal full-sized application.
  41. *
  42. *    This application is an example of the form of a Macintosh 
  43. *    application; it is NOT a template. It is NOT intended to be 
  44. *    used as a foundation for the next world-class, best-selling, 
  45. *    600K application. A stick figure drawing of the human body may 
  46. *    be a good example of the form for a painting, but that does not 
  47. *    mean it should be used as the basis for the next Mona Lisa.
  48. *
  49. *    We recommend that you review this program or TESample before 
  50. *    beginning a new application.
  51.  
  52. * This example program is to be considered an introduction to coding in the
  53. * MPW Assembly language.  This sample program demonstrates the use of RECORD,
  54. * PROC, WITH, MACROs, IMPORT, and other coding practices used by MPW.  Although
  55. * this code will not be compatible with other assemblers, there is enough code
  56. * contained within the procedures that demonstrate 68000 programming on the Mac.
  57.  
  58. * The main purpose of this example is to have an easy to understand sample
  59. * assembly program that follows very closely the same sample program available
  60. * in Pascal and C.  Programmers not familiar with assembly code should refer to
  61. * these high level versions and follow the procedures while examining the assembly
  62. * code.  This is a great way to learn how to read assembly listings, and that is
  63. * the first step in using a debugger.
  64.  
  65. * Stack frame strategy:
  66. * -----------------------------------------------
  67. * Here is an example of a typical stack frame.  An example of the stack frame
  68. * RECORD is shown.  Using this strategy for procedures makes life much easier
  69. * while writing assembly code.  The procedure outlined in Pascal here is
  70. * followed by the same outline in assembly.
  71.  
  72. * PROCEDURE MyProcedure (Param1: type, Param2: type, ParamN: type) Result1: type;
  73.  
  74. * VAR    Local1: type;
  75. *    Local2: type;
  76. *    LocalN: type;
  77.  
  78.  
  79. * MyProcedure    PROC    EXPORT            ; any source file can use this routine
  80.  
  81. * define registors that need to be saved as EQUATES (typically A3-A7 and D4-D7)
  82.  
  83. * StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  84. * Result1    DS.{size}            ; function's result returned to caller
  85. * ParamBegin    EQU    *            ; start parameters after this point
  86. * Param1    DS.{size}            ; the first parameter on the stack
  87. * Param2    DS.{size}            ; rest of the parameters passed by caller
  88. * ParamN    DS.{size}            ; the last parameter passed by caller
  89. * ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  90. * RetAddr     DS.L    1            ; place holder for return address
  91. * A6Link    DS.L    1            ; place holder for A6 link
  92. * Local1    DS.{size}            ; a local variable for this procedure only
  93. * Local2    DS.{size}            ; other local variables for this procedure
  94. * LocalN    DS.{size}            ; the last local variable
  95. * LocalSize    EQU     *            ; size of all the local variables
  96. *         ENDR
  97.  
  98. *         WITH    StackFrame        ; cover our local stack frame
  99. *         LINK    A6,#LocalSize        ; allocate our local stack frame
  100.  
  101. *        save registors trashed by this routine
  102.  
  103. *         # # INSERT YOUR CODE HERE # #
  104.  
  105. * Exit        restore registors trashed by this routine
  106. *         UNLK    A6            ; destroy the link
  107. *         MOVEA.L    (SP)+,A0        ; pull off the return address
  108. *         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  109. *         JMP    (A0)            ; return to the caller
  110. *         DbgInfo    MyProcedure        ; this name will appear in the debugger
  111. *         ENDP
  112.  
  113. * The Macro DbgInfo is optional.  I prefer to use it, since it aids in
  114. * debugging.  There are more macros in the "AStructMacs" folder of MPW.  Put on
  115. * a pot of coffee and take a look at them and the Sample program that uses these
  116. * macros.  There is one macro in particular that builds the entire stack frame
  117. * structure as outlined above, including the debug info.
  118.  
  119. * Segmentation strategy:
  120. * -----------------------------------------------
  121. * This program consists of three segments. Main contains most of the code.
  122. * Initialize contains code that is only used once, during startup, and can be
  123. * unloaded after the program starts. %A5Init is automatically created by the
  124. * Linker to initialize globals and constants, and is unloaded right away.
  125.  
  126. * SetPort strategy:
  127. * -----------------------------------------------
  128. * Tool box routines do not change the current port. In spite of this, in this
  129. * program we use a strategy of calling SetPort whenever we want to draw or
  130. * make calls which depend on the current port. This makes us less vulnerable
  131. * to bugs in other software which might alter the current port (such as the
  132. * bug (feature?) in many desk accessories which change the port on OpenDeskAcc).
  133. * Hopefully, this also makes the routines from this program more self-contained,
  134. * since they don't depend on the current port setting.
  135.  
  136. * ================================================
  137. * -------------- INCLUDES SECTION ----------------
  138. * ================================================
  139.     
  140.     PRINT    PUSH,OFF            ; don't print any of this stuff
  141.  
  142.     INCLUDE    'ToolEqu.a'
  143.     INCLUDE    'Traps.a'
  144.     INCLUDE    'PackMacs.a'
  145.     INCLUDE    'QuickEqu.a'
  146.     INCLUDE    'SysEqu.a'
  147.     INCLUDE    'Sample.inc1.a'            ; all our macros and data templates
  148.  
  149.     PRINT    POP                ; restore the PRINT options
  150.     
  151.  
  152. * ================================================
  153. * ---------  DATA STORAGE ALLOCATION  ------------
  154. * ================================================
  155. * Global data storage.  All global memory is allocated here.  The
  156. * Linker will load all global data offset from A5, and the Asm knows this.
  157. * Therefore, no reference to (A5) is required in the code. Hooray!
  158. * Here we declare two data structures using our templates defined previously.
  159. * They must be EXPORTed here for other files that need to IMPORT them.
  160.  
  161.         EXPORT    (QD,G):DATA
  162.  
  163. QD        DS    QDGlobals        ; QuickDraw's globals
  164. G        DS    AppGlobals        ; application's globals
  165.  
  166.  
  167. * ================================================
  168. * PROCEDURE Initialize;
  169. * ================================================
  170. * Set up the whole world, including global variables, Toolbox managers, and menus.
  171. * Check to see if a given trap is implemented. The recommended approach to see if
  172. * a trap is implemented is to see if the address of the trap routine is the same
  173. * as the address of the Unimplemented trap.  We also create our one application
  174. * window at this time.  Since window storage is non-relocateable, how and when to
  175. * allocate space for windows is very important so that heap fragmentation does not
  176. * occur.  Because Sample has only one window and it is only disposed when the
  177. * application quits, we will allocate its space here, before anything that might
  178. * be a locked relocatable object gets into the heap. This way, we can force its
  179. * storage to be in the lowest memory available in the heap. Window storage can
  180. * differ widely amongst applications depending on how many windows are created
  181. * and disposed.  If a failure occurs here, we will consider that the application
  182. * is in such bad shape that we should just exit. Your error handling may differ,
  183. * but the checks should still be made.
  184.  
  185. * If an error is detected, instead of merely doing an ExitToShell, which leaves
  186. * the user without much to go on, we call AlertUser, which puts up a simple alert
  187. * that just says an error occurred and then calls ExitToShell.  In the interests
  188. * of keeping things simple, the alert does not state the specific cause of the error,
  189. * but a more informative alert would be appropriate for more sophisticated applications.
  190. * Since there is no other cleanup needed at this point if an error is detected, this
  191. * form of error- handling is acceptable. If more sophisticated error recovery is needed,
  192. * a signal mechanism, such as is provided by Signals, can be used.
  193.  
  194. * Something worth noting here.  Since the AlertUser routine is in a different segment,
  195. * we have to use a Jump instruction to get there.  In other words, we must go through the
  196. * jump table.  This causes extra test and branch instructions to get over the JMP AlertUser.
  197.  
  198.         SEG 'Initialize'        ; case sensitive
  199. Initialize    PROC                ; Initialize everything
  200.  
  201. CountReg    EQU    D4            ; temporary registor to count loops
  202.  
  203. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  204. ParamBegin    EQU    *            ; start parameters after this point
  205. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  206. RetAddr     DS.L    1            ; place holder for return address
  207. A6Link        DS.L    1            ; place holder for A6 link
  208. CurMBar        DS.L    1            ; local handle to our menubar
  209. TheEvent     DS    EventRecord         ; local copy of the event record
  210. LocalSize    EQU     *            ; size of all the local variables
  211.         ENDR
  212.         
  213.         IMPORT    GoGetRect,AlertUser,SysEnvirons,    \
  214.             TrapAvailable        ; linked in with Interface.o
  215.  
  216.         WITH    StackFrame        ; cover our local stack frame
  217.         LINK    A6,#LocalSize        ; allocate our local stack frame
  218.         
  219.         MOVEM.L    CountReg,-(SP)         ; save the current registor values
  220.         MOVE.W    #False,G.InBackground    ; we start out in the foreground
  221.         MOVE.W    #True,G.Stopped        ; we'll start with the red light on
  222.  
  223. * ------------- INITIALIZE MANAGERS -------------
  224.  
  225. @1        PEA     QD.GrafPort         ; initialize all of the Managers
  226.         _InitGraf            ; please don't flush my events
  227.         _InitFonts
  228.         _InitWindows
  229.         _InitMenus
  230.         _TEInit
  231.         CLR.L    -(SP)    
  232.         _InitDialogs
  233.         _InitCursor
  234.         
  235. * Call MPPOpen and ATPLoad at this point to initialize AppleTalk, if you are using it.
  236. * NOTE -- It is no longer necessary, and actually unhealthy, to check PortBUse and
  237. * SPConfig before opening AppleTalk. The drivers are capable of checking for port
  238. * availability themselves.  This next bit of code is necessary to allow the default
  239. * button of our alert be outlined.
  240.      
  241. * ------------- WASTE THREE EVENTS -------------
  242.  
  243.         MOVE.W    #2,CountReg        ; set register value to loop 3 times
  244. Loop        CLR.W    -(SP)            ; space for result
  245.         MOVE.W    #EveryEvent,-(SP)    ; the events we want
  246.         PEA    TheEvent(A6)        ; pass a pointer to our event
  247.         _EventAvail
  248.         MOVE.W    (SP)+,D0        ; result code
  249.         DBF    CountReg,Loop        ; decrement count, if count < 0 then continue
  250.  
  251. * ------------- GET THE ENVIRONMENT -------------
  252.  
  253.         CLR.W    -(SP)            ; create space for result
  254.         MOVE.W    #EnvironsVersion,-(SP)    ; version of SysEnvirons we want
  255.         PEA    G.Mac            ; the global environment record
  256.         JSR    SysEnvirons        ; we can ignore any errors here,
  257.         MOVE.W    (SP)+,D0        ; SysEnvirons will fill in regardless
  258.         MOVE.W    G.Mac.MachineType,D0     ; negitive value means old ROMs
  259.         BPL.S    @2            ; 128k ROMs or better, continue on
  260.         JMP    AlertUser        ; we don't want to run on 64k ROMs
  261.  
  262. * ------------- TEST FOR WAITNEXTEVENT -------------
  263. * 1.02 - Move TrapAvailable call to after SysEnvirons so that
  264. * we can tell in TrapAvailable if a tool trap value is out of range.
  265.  
  266. @2        CLR.W    -(SP)            ; space for result of trap test
  267.         MOVE.W    #WaitNextEvent,-(SP)    ; pass the trap number of WaitNextEvent trap
  268.         BSR    TrapAvailable        ; test for this trap
  269.         MOVE.W    (SP)+,G.HasWNEvent    ; put the result in our global flag
  270.             
  271. * ------------- CHECK FOR ENOUGH MEMORY -------------
  272. * It is better to first check the size of the application heap against a value
  273. * that you have determined is the smallest heap the application can reasonably
  274. * work in. This number should be derived by examining the size of the heap that
  275. * is actually provided by MultiFinder when the minimum size requested is used.
  276. * The derivation of the minimum size requested from MultiFinder is described
  277. * in ASample.r. The check should be made because the preferred size can end up
  278. * being set smaller than the minimum size by the user. This extra check acts to
  279. * insure that your application is starting from a solid memory foundation.
  280.  
  281. *    IF applLimit - applZone < MinHeap THEN AlertUser
  282.  
  283. * Next, make sure that enough memory is free for your application to run. It
  284. * is possible for a situation to arise where the heap may have been of required
  285. * size, but a large scrap was loaded which left too little memory. To check for
  286. * this, call PurgeSpace and compare the result with a value that you have determined
  287. * is the minimum amount of free memory your application needs at initialization.
  288. * This number can be derived several different ways. One way that is fairly
  289. * straightforward is to run the application in the minimum size configuration
  290. * as described previously. Call PurgeSpace at initialization and examine the value
  291. * returned. However, you should make sure that this result is not being modified
  292. * by the scrap's presence. You can do that by calling ZeroScrap before calling
  293. * PurgeSpace. Make sure to remove that call before shipping, though.
  294.  
  295. * The extra benefit to waiting until after the Toolbox Managers have been initialized
  296. * before checking memory is that we can now give the user an alert to tell him what
  297. * happened. Although it is possible that the memory situation could be worsened by
  298. * displaying an alert, MultiFinder would gracefully exit the application with
  299. * an informative alert if memory became critical. Here we are acting more
  300. * in a preventative manner to avoid future disaster from low-memory problems.
  301.  
  302.         MOVE.L    applLimit,D1        ; get pointer to ApplLimit
  303.         MOVE.L    applZone,D0        ; get pointer to ApplicZone
  304.         SUB.L    D0,D1            ; subtract the ApplicZone from ApplLimit
  305.         CMPI.L    #MinHeap,D1        ; do we have enough memory?
  306.         BPL.S    @3            ; yes we do, continue on
  307.         JMP    AlertUser        ; no, report the error
  308.         
  309. @3        _PurgeSpace            ; results will be in A0 and D0
  310.         CMPI.L    #MinSpace,D0        ; do we have enough purgeable space?
  311.         BPL.S    @4
  312.         JMP    AlertUser        ; no, report the error
  313.  
  314. * ------------- SET UP THE TRAFFIC LIGHT WINDOW -------------
  315. * We will allocate our own window storage instead of letting the Window Manager
  316. * for two reasons. One, GetNewWindow locks the 'WIND' resource handle before calling
  317. * NewWindow and this can lead to heap fragmentation.  Two, it takes just as much time
  318. * for NewWindow to get the memory as it does for us to get it.
  319.  
  320. @4        MOVE.L    #windowSize,D0
  321.         _NewPtr ,Clear            ; create a pointer in A0 and clear memory
  322.         CMPA.L    #NIL,A0            ; check for NIL pointer (result in D0)
  323.         BNE.S    @5            ; must have been a valid pointer
  324.         JMP    AlertUser        ; couldn't get memory, report error
  325.         
  326. @5        CLR.L    -(SP)            ; create space for result
  327.         MOVE.W    #rWindow,-(SP)        ; out window resource definition
  328.         MOVE.L    A0,-(SP)        ; our window record storage
  329.         MOVE.L    #-1,-(SP)        ; make it on top
  330.         _GetNewWindow            ; create the window
  331.         MOVE.L    (SP)+,D0        ; we're not saving our window pointer
  332.         
  333. * ------------- SET UP THE MENUS -------------
  334.     
  335.         CLR.L    -(SP)            ; space for MenuBar handle
  336.         MOVE.W    #rMenuBar,-(SP)        ; our MenuBar resource
  337.         _GetNewMBar            ; the modern way, get a MenuBar
  338.         MOVE.L    (SP),CurMBar(A6)
  339.         _SetMenuBar
  340.         MOVEA.L    CurMBar(A6),A0        ; we're done with that handle
  341.         _DisposHandle            ; there is a result in D0
  342.         CLR.L    -(SP)
  343.         MOVE.W    #AppleMenu,-(SP)
  344.         _GetMHandle            ; put Apple menu handle on stack
  345.         MOVE.L    #'DRVR',-(SP)        ; get all the DAs
  346.         _AddResMenu
  347.         _DrawMenuBar
  348.  
  349. * ------------- SET UP RECTS FOR THE LIGHTS  -------------
  350.  
  351.         CLR.W    -(SP)            ; space for result of GoGetRect
  352.         MOVE.W    #rStopRect,-(SP)    ; pass the stop light's rect
  353.         PEA    G.StopRect        ; pass the stop light's rect pointer
  354.         BSR    GoGetRect        ; go get the stop light rect
  355.         MOVE.W    (SP)+,D0        ; get the result of GoGetRect
  356.         CMPI.W    #True,D0        ; did we get the RECT resource?
  357.         BEQ.S    @6            ; yes, then continue
  358.         JMP    AlertUser        ; otherwise, we're having some trouble
  359.         
  360. @6        CLR.W    -(SP)            ; space for result of GoGetRect
  361.         MOVE.W    #rGoRect,-(SP)        ; pass the go light's rect
  362.         PEA    G.GoRect        ; pass the go light's rect pointer
  363.         BSR    GoGetRect        ; go get the go light rect
  364.         MOVE.W    (SP)+,D0        ; get the result of GoGetRect
  365.         CMPI.W    #True,D0        ; did we get the RECT resource?
  366.         BEQ.S    Exit            ; yes, then continue
  367.         JMP    AlertUser        ; otherwise, we're having some trouble
  368.                 
  369. Exit        MOVEM.L    (SP)+,CountReg        ; restore the registors
  370.         UNLK    A6            ; destroy the link
  371.         MOVEA.L    (SP)+,A0        ; pull off the return address
  372.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  373.         JMP    (A0)            ; return to the caller
  374.  
  375.         DbgInfo    Initialz        ; this name will appear in the debugger
  376.         ENDP
  377.  
  378. * ================================================
  379. * PROCEDURE DoContentClick(window: WindowPtr; event: EventRecord);
  380. * ================================================
  381. * This is called when a mouse-down event occurs in the content of a window.
  382. * Other applications might want to call FindControl, TEClick, etc., to
  383. * further process the click.
  384.  
  385.         SEG    'Main'            ; case sensitive
  386. DoContentClick    PROC
  387.  
  388. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  389. ParamBegin    EQU    *            ; start parameters after this point
  390. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  391. EventPtr    DS.L    1            ; pointer to the event record
  392. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  393. RetAddr     DS.L    1            ; place holder for return address
  394. A6Link        DS.L    1            ; place holder for A6 link
  395. LocalSize    EQU     *            ; size of all the local variables
  396.         ENDR
  397.         
  398.         IMPORT    SetLight
  399.  
  400.         WITH    StackFrame        ; cover our local stack frame
  401.         LINK    A6,#LocalSize        ; allocate our local stack frame
  402.  
  403.          MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  404.         MOVE.W    G.Stopped,D0        ; get current state of the light
  405.         EORI.W    #True,D0        ; exclusive OR the current state
  406.         MOVE.W    D0,-(SP)        ; pass new state to switch light
  407.         BSR    SetLight        ; set the traffic light
  408.  
  409. Exit        UNLK    A6            ; destroy the link
  410.         MOVEA.L    (SP)+,A0        ; pull off the return address
  411.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  412.         JMP    (A0)            ; return to the caller
  413.  
  414.         DbgInfo    DoContnt        ; this name will appear in the debugger
  415.         ENDP
  416.  
  417. * ================================================
  418. * PROCEDURE DoUpdate(window: WindowPtr);
  419. * ================================================
  420. * This is called when an update event is received for a window.
  421. * It calls DrawWindow to draw the contents of an application window.
  422. * As an efficiency measure that does not have to be followed, it
  423. * calls the drawing routine only if the visRgn is non-empty. This
  424. * will handle situations where calculations for drawing or drawing
  425. * itself is very time-consuming.
  426.  
  427.         SEG    'Main'            ; case sensitive
  428. DoUpdate    PROC
  429.  
  430. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  431. ParamBegin    EQU    *            ; start parameters after this point
  432. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  433. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  434. RetAddr     DS.L    1            ; place holder for return address
  435. A6Link        DS.L    1            ; place holder for A6 link
  436. LocalSize    EQU     *            ; size of all the local variables
  437.         ENDR
  438.         
  439.         IMPORT    IsAppWindow,DrawWindow
  440.  
  441.         WITH    StackFrame        ; cover our local stack frame
  442.         LINK    A6,#LocalSize        ; allocate our local stack frame
  443.  
  444.         CLR.W    -(SP)            ; space for result of IsAppWindow
  445.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  446.         BSR    IsAppWindow        ; test if this window was ours
  447.         MOVE.W    (SP)+,D0        
  448.         CMPI.W    #True,D0        ; it must be our window
  449.         BNE.S    Exit            ; it wasn't our window
  450.         
  451.         MOVE.L    WindowPtr(A6),-(SP)    ; update only the visible region
  452.         _BeginUpDate            ; region of the window
  453.         CLR.W    -(SP)            ; space for result
  454.         MOVEA.L    WindowPtr(A6),A0    ; the window pointer
  455.         MOVE.L    visRgn(A0),-(SP)    ; the window's visRgn handle
  456.         _EmptyRgn
  457.         MOVE.W    (SP)+,D0        ; result of EmptyRgn
  458.         CMPI.W    #True,D0        ; was the visRgn empty?
  459.         BEQ.S    @1            ; yes, then no update is needed
  460.         
  461.         MOVE.L    WindowPtr(A6),-(SP)
  462.         BSR    DrawWindow        ; draw the traffic lights
  463.         
  464. @1        MOVE.L    WindowPtr(A6),-(SP)    ; get pointer to window
  465.         _EndUpdate
  466.  
  467. Exit        UNLK    A6            ; destroy the link
  468.         MOVEA.L    (SP)+,A0        ; pull off the return address
  469.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  470.         JMP    (A0)            ; return to the caller
  471.  
  472.         DbgInfo    DoUpdate        ; this name will appear in the debugger
  473.         ENDP
  474.  
  475. * ================================================
  476. * PROCEDURE DoActivate(window: WindowPtr; becomingActive: BOOLEAN);
  477. * ================================================
  478. * In this sample there is no other processing necessary other than what
  479. * the Window Manager has already done for us.  This would be the place to
  480. * perform an activate on TextEdit records, controls, lists, update GrowIcon, etc.
  481.  
  482.         SEG    'Main'            ; case sensitive
  483. DoActivate    PROC
  484.  
  485. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  486. ParamBegin    EQU    *            ; start parameters after this point
  487. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  488. Active        DS.W    1            ; modifiers from the event record
  489. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  490. RetAddr     DS.L    1            ; place holder for return address
  491. A6Link        DS.L    1            ; place holder for A6 link
  492. LocalSize    EQU     *            ; size of all the local variables
  493.         ENDR
  494.         
  495.         IMPORT    IsAppWindow
  496.  
  497.         WITH    StackFrame        ; cover our local stack frame
  498.         LINK    A6,#LocalSize        ; allocate our local stack frame
  499.  
  500.         CLR.W    -(SP)            ; space for result of IsAppWindow
  501.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  502.         BSR    IsAppWindow        ; test if this window was ours
  503.         MOVE.W    (SP)+,D0        ; get the result
  504.         CMPI.W    #True,D0        ; it must be our window
  505.         BNE.S    Exit            ; it wasn't our window
  506.  
  507.         CMPI.W    #True,Active(A6)    ; was it an Activate?
  508.         BNE.S    DeActivate        ; no, perform a Deactivate
  509.         
  510. * do the activate event processing here, then "BRA.S   Exit"
  511.         
  512. DeActivate                    ; do the deactivate event
  513.  
  514. * do the deactivate event processing here, then fall through to Exit
  515.         
  516.  
  517. Exit        UNLK    A6            ; destroy the link
  518.         MOVEA.L    (SP)+,A0        ; pull off the return address
  519.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  520.         JMP    (A0)            ; return to the caller
  521.  
  522.         DbgInfo    Activate        ; this name will appear in the debugger
  523.         ENDP
  524.                     
  525. * ================================================
  526. * PROCEDURE DoMenuCommand(menuResult: LONGINT);
  527. * ================================================
  528. * This is called when an item is chosen from the menu bar (after calling
  529. * MenuSelect or MenuKey). It performs the right operation for each command.
  530. * It is good to have both the result of MenuSelect and MenuKey go to
  531. * one routine like this to keep everything organized.
  532.  
  533.         SEG    'Main'            ; case sensitive
  534. DoMenuCommand    PROC
  535.  
  536. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  537. ParamBegin    EQU    *            ; start parameters after this point
  538. MenuItem    DS.W    1            ; result from _MenuKey or _MenuSelect
  539. MenuID        DS.W    1            ; caller passed a long word, ID + Item
  540. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  541. RetAddr     DS.L    1            ; place holder for return address
  542. A6Link        DS.L    1            ; place holder for A6 link
  543. Deskname    DS.B    256            ; local storage for Desk Accs name
  544. TempPort    DS.L    1            ; local storage for the current port
  545. LocalSize    EQU     *            ; size of all the local variables
  546.         ENDR
  547.         
  548.         IMPORT    SetLight,DoCloseWindow,Terminate
  549.  
  550.         WITH    StackFrame        ; cover our local stack frame
  551.         LINK    A6,#LocalSize        ; allocate our local stack frame
  552.  
  553.         MOVE.W    MenuID(A6),D0        ; a nifty Pascal case-like macro
  554.         CASE#.W    (D0,IF),            \
  555.             (AppleMenu,    DoAppleMenu),    \
  556.             (FileMenu,    DoFileMenu),    \
  557.             (EditMenu,    DoEditMenu),    \
  558.             (LightMenu,    DoLightMenu)
  559.                         ; add additional Menus would go here
  560.         BRA.W    Exit            ; otherwise we will exit this procedure
  561.  
  562. * ------------- THE APPLE MENU ROUTINES -------------
  563. DoAppleMenu
  564.         CMPI.W    #AboutItem,MenuItem(A6)    ; was it the about item?
  565.         BNE.S    @1            ; no, must be a Desk Acc
  566.  
  567.         CLR.W    -(SP)            ; show the About dialog
  568.         MOVE.W    #rAboutAlert,-(SP)    ; resource for alert dialog
  569.         CLR.L    -(SP)            ; no filter procedure used here
  570.         _Alert                ; read the resource and display it
  571.         MOVE.W    (SP)+,D0        ; I don't care which item is was
  572.         BRA.W    Exit            ; all done with with Apple menu
  573.  
  574. @1        PEA    TempPort(A6)        ; open a desk accessory
  575.         _GetPort            ; save the current port
  576.         CLR.L    -(SP)            ; space for result of GetMHandle
  577.         MOVE.W    #AppleMenu,-(SP)
  578.         _GetMHandle            ; put Apple menu on stack
  579.         MOVE.W    MenuItem(A6),-(SP)    ; and here's the MenuItem
  580.         PEA    DeskName(A6)        ; now tell me the DA's name
  581.         _GetItem
  582.         CLR.W    -(SP)            ; space for OpenDeskAcc result
  583.         PEA    DeskName(A6)
  584.         _OpenDeskAcc            ; open that puppy
  585.         MOVE.W    (SP)+,D0        ; result
  586.         MOVE.L    TempPort(A6),-(SP)    ; restore the port
  587.         _SetPort
  588.         BRA.S    Exit
  589.         
  590. * ------------- THE FILE MENU ROUTINES -------------
  591. DoFileMenu    
  592.         MOVE.W    MenuItem(A6),D0     ; test the MenuItem
  593.         Case#.W    (D0,IF),            \
  594.             (CloseItem,    FileClose),    \
  595.             (QuitItem,    FileQuit)
  596.         BRA.S    Exit            ; add additional menus here
  597. FileClose
  598.         CLR.L    -(SP)            ; bug fix, didn't clear space for result -JDR 2/27/89
  599.         _FrontWindow
  600.         BSR    DoCloseWindow        ; close the window 
  601.         BRA.S    Exit
  602.  
  603. FileQuit    BSR    Terminate        ; let's get out of here
  604.         BRA.S    Exit            ; Terminate may return if user cancels
  605.  
  606. * ------------- THE EDIT MENU ROUTINES -------------
  607. DoEditMenu    
  608.         CLR.W    -(SP)            ; system will handle editing of desk accs.
  609.         MOVE.W    MenuItem(A6),-(SP)    ; get the MenuItem
  610.         SUBQ.W    #1,(SP)            ; SystemEdit is off by one
  611.         _SysEdit
  612.         MOVE.B    (SP)+,D0        ; drop result from SystemEdit
  613.         BRA.S    Exit            ; we don't have anything to edit
  614.  
  615. * ------------- THE LIGHT MENU ROUTINES -------------
  616. DoLightMenu    
  617.         MOVE.W    MenuItem(A6),D0     ; test the MenuItem
  618.         Case#.W    (D0,IF),            \
  619.             (StopItem,    StopSelect),    \
  620.             (GoItem,    GoSelect)
  621.         BRA.S    Exit            ; add additional menus here
  622.  
  623. StopSelect    CLR.L    -(SP)            ; bug fix, didn't clear space for result -JDR 2/27/89
  624.         _FrontWindow            ; pass our window, we only have one
  625.         MOVE.W    #TRUE,-(SP)        ; pass true to set stop light on
  626.         BSR    SetLight        ; switch the traffic light
  627.         BRA.S    Exit
  628.  
  629. GoSelect    CLR.L    -(SP)            ; bug fix, didn't clear space for result -JDR 2/27/89
  630.         _FrontWindow            ; pass our window, we only have one
  631.         MOVE.W    #FALSE,-(SP)        ; pass false to set stop light off
  632.         BSR    SetLight        ; switch the traffic light
  633.         
  634. Exit        CLR.W    -(SP)    
  635.         _HiLiteMenu            ; unhilite all Menus
  636.         UNLK    A6            ; destroy the link
  637.         MOVEA.L    (SP)+,A0        ; pull off the return address
  638.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  639.         JMP    (A0)            ; return to the caller
  640.  
  641.         DbgInfo    DoMenuCm        ; this name will appear in the debugger
  642.         ENDP
  643.         
  644. * ================================================
  645. * PROCEDURE DoMouseDown(Event: EventRecord);
  646. * ================================================
  647. * Handle all of the MouseDown events.
  648.  
  649.         SEG    'Main'            ; case sensitive
  650. DoMouseDown    PROC
  651.  
  652. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  653. ParamBegin    EQU    *            ; start parameters after this point
  654. EventPtr     DS.L    1             ; pointer to current event
  655. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  656. RetAddr     DS.L    1            ; place holder for return address
  657. A6Link        DS.L    1            ; place holder for A6 link
  658. WindowPtr    DS.L    1            ; local Window pointer variable
  659. Where        DS.L    1            ; local variable where the click was
  660. NewGrowRect    DS    Rect            ; local rect variable for SizeWindow
  661. LocalSize    EQU     *            ; size of all the local variables
  662.         ENDR
  663.  
  664.         IMPORT    AdjustMenus,DoContentClick
  665.  
  666.         WITH    StackFrame        ; cover our local stack frame
  667.         LINK    A6,#LocalSize        ; allocate our local stack frame
  668.         
  669.         MOVEA.L    EventPtr(A6),A0        ; event record only needed by SystemClick
  670.         MOVE.L    evtMouse(A0),Where(A6)    ; make a local copy of the mouse location
  671.  
  672.         CLR.W    -(SP)            ; space for FindWindow result
  673.         MOVE.L    Where(A6),-(SP)        ; the mouse point
  674.         PEA    WindowPtr(A6)        ; a local variable
  675.         _FindWindow            ; put the result in a register
  676.         MOVE.W    (SP)+,D0        ; a nifty Pascal case-like macro
  677.         Case#.W    (D0,IF),            \
  678.             (InMenuBar,    MenuEvent),    \
  679.             (InSysWindow,    SystemEvent),    \
  680.             (InContent,    Content),    \
  681.             (InDrag,    Drag)
  682.                         ; add additional routines here
  683.         BRA.S    Exit            ; otherwise we will exit this procedure
  684.  
  685. * ------------- THE DESK ACCS EVENT -------------
  686. MenuEvent    
  687.         BSR.W    AdjustMenus
  688.         CLR.L    -(SP)            ; space for MenuSelect
  689.         MOVE.L    Where(A6),-(SP)        ; Mouse coordinates
  690.         _MenuSelect            ; pass MenuSelect's result
  691.         BSR    DoMenuCommand        ; go do the menu and return
  692.         BRA.S    Exit
  693.  
  694. * ------------- THE DESK ACCS EVENT -------------
  695. SystemEvent    
  696.         MOVE.L    EventPtr(A6),-(SP)    ; get EventRecord and WindowPtr
  697.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer and...
  698.         _SystemClick            ; let the system handle it
  699.         BRA.S    Exit
  700.  
  701. * ------------- THE CONTENT EVENT -------------
  702. Content        
  703.         CLR.L    -(SP)            ; was our window in front?
  704.         _FrontWindow            ; get front window's pointer
  705.         MOVE.L    (SP)+,D0
  706.         CMP.L    WindowPtr(A6),D0    ; was it in the front window?
  707.         BNE.S    @1            ; no, then just select window
  708.         
  709.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  710.         MOVE.L    EventPtr(A6),-(SP)    ; pass a pointer to the event
  711.         BSR    DoContentClick        ; do a click in content region
  712.         BRA.S    Exit
  713.         
  714. @1        MOVE.L    WindowPtr(A6),-(SP)    ; only select this window
  715.         _SelectWindow            ; and take no further action
  716.         BRA.S    Exit
  717.  
  718. * ------------- THE DRAG A WINDOW EVENT -------------
  719. Drag        
  720.         MOVE.L    WindowPtr(A6),-(SP)    ; pass Window Pointer
  721.         MOVE.L    Where(A6),-(SP)        ; Mouse coordinates and boundary
  722.         PEA    QD.Screenbits.bounds    
  723.         _DragWindow            ; drag it the screen's boundary
  724.  
  725. Exit        
  726.         UNLK    A6            ; destroy the link
  727.         MOVEA.L    (SP)+,A0        ; pull off the return address
  728.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  729.         JMP    (A0)            ; return to the caller
  730.  
  731.         DbgInfo    MouseDwn        ; this name will appear in the debugger
  732.         ENDP
  733.         
  734.         
  735. * ================================================
  736. * PROCEDURE DoEvent(event: EventRecord);
  737. * ================================================
  738. * Do the right thing for an event. Determine what kind of event it is,
  739. * and call the appropriate routines.
  740.  
  741.         SEG    'Main'            ; case sensitive
  742. DoEvent        PROC
  743.  
  744. ModifyReg    EQU    D4            ; we'll use this register locally
  745.  
  746. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  747. ParamBegin    EQU    *            ; start listing parameters here
  748. EventPtr     DS.L    1             ; pointer to current event
  749. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  750. RetAddr     DS.L    1            ; place holder for return address
  751. A6Link        DS.L    1            ; place holder for A6 link
  752. TheEvent     DS    EventRecord         ; local copy of the event record
  753. LocalSize    EQU     *            ; size of all the local variables
  754.         ENDR
  755.  
  756.         IMPORT    DoMouseDown,DrawWindow,    \
  757.             AdjustMenus,IsAppWindow,\
  758.             DoUpdate,DoActivate
  759.         
  760.         WITH    StackFrame,TheEvent    ; cover our local stack frame
  761.         LINK    A6,#LocalSize        ; allocate our local stack frame
  762.         MOVEM.L    ModifyReg,-(SP)        ; save this register before using it
  763.  
  764.         MOVEA.L    EventPtr(A6),A0        ; pointer of event passed by caller
  765.         LEA    TheEvent(A6),A1        ; pointer to local variable TheEvent
  766.         MOVE.L    #evtBlkSize,D0        ; size of an event record
  767.         _BlockMove            ; we now have a local copy of the event
  768.  
  769.         MOVE.W    Modify(A6),ModifyReg    ; a nifty Pascal case-like macro
  770.         MOVE.W    What(A6),D0        ; get the event number
  771.         Case#    (D0,Exit),    \    ; if not an event we support, then exit
  772.             ,        \    ;  0 Null (not used)
  773.             MouseDown,    \    ;  1 Mouse down
  774.             ,        \    ;  2 Mouse up (not used)
  775.             KeyDown,    \    ;  3 Key down
  776.             ,        \    ;  4 Key up (not used)
  777.             KeyDown,    \    ;  5 Auto key
  778.             Update,     \    ;  6 Update
  779.             Disk,        \    ;  7 Disk inserted
  780.             Activate,    \    ;  8 Activate/Deactivate
  781.             ,        \    ;  9 (not used)
  782.             ,        \    ; 10 Network (not used)
  783.             ,        \    ; 11 I/O Driver (not used)
  784.             ,        \    ; 12 App1 (not used)
  785.             ,        \    ; 13 App2 (not used)
  786.             ,        \    ; 14 App3 (not used)
  787.             OSEvent,        ; 15 OS Event or Suspend/Resume
  788.  
  789.  
  790. * ------------- THE MOUSEDOWN EVENT -------------
  791. MouseDown    
  792.         PEA    TheEvent(A6)        ; pass Event pointer in case of SystemClick
  793.         BSR    DoMouseDown
  794.         BRA    Exit
  795.  
  796. * ------------- THE KEYDOWN EVENT -------------
  797. KeyDown        
  798.         BTST    #CmdKey,ModifyReg    ; command key?
  799.         BEQ    Exit            ; no, then we're done
  800.         BSR.W    AdjustMenus        ; first, adjust the menus
  801.         CLR.L    -(SP)            ; space for MenuKey
  802.         MOVE.W    2+Message(A6),-(SP)    ; get the character
  803.         _MenuKey            ; is it a command?
  804.         BSR    DoMenuCommand        ; handle the command and return
  805.         BRA.S    Exit
  806.  
  807. * ------------- THE UPDATE EVENT -------------
  808. Update    
  809.         MOVE.L    Message(A6),-(SP)    ; pass the window pointer
  810.         BSR    DoUpdate        ; do the update
  811.         BRA.S    Exit
  812.  
  813. * ------------- THE DISK EVENT -------------
  814. Disk    
  815.         TST.W    Message(A6)        ; check for error
  816.         BEQ.S    @1            ; if none, skip
  817.         CLR.W    -(SP)
  818.         MOVE.L    #DITopLeft,-(SP)
  819.         MOVE.L    Message(A6),-(SP)
  820.         MOVE.W    #diBadMount,-(SP)
  821.         _Pack2                ; go through disk init package
  822.         ADDQ    #2,SP            ; throw away result
  823. @1        BRA.S    Exit
  824.  
  825. * ------------- THE ACTIVATE/DEACTIVATE EVENT -------------
  826. Activate    
  827.         BTST    #ActiveFlag,ModifyReg    ; was it an Activate?
  828.         BEQ.S    @1            ; no, perform a Deactivate
  829.  
  830.         MOVE.L    Message(A6),-(SP)    ; pass the current window pointer
  831.         MOVE.W    #True,-(SP)        ; set up for an Activate event
  832.         BSR    DoActivate        ; do the activate routine
  833.         BRA.S    Exit            ; we're done
  834.  
  835. @1        MOVE.L    Message(A6),-(SP)    ; pass current window pointer
  836.         MOVE.W    #False,-(SP)        ; set up for an Deactivate event
  837.         BSR    DoActivate        ; go do the activate routine
  838.         BRA.S    Exit            ; we're done
  839.  
  840. * ------------- THE SUSPEND/RESUME EVENT -------------
  841. * OSEvent is the event number of the suspend/resume and mouse-moved events sent
  842. * by MultiFinder. Once we determine that an event is an osEvent, we look at the
  843. * high byte of the message sent to determine which kind it is. To differentiate
  844. * suspend and resume events we check the resumeMask bit.
  845.  
  846. OSEvent        MOVE.B    Message(A6),D1        ; get high byte of Message in reg
  847.         CMPI.B    #SuspendResume,D1    ; test for message event type
  848.         BNE.S    Exit            ; not a suspend/resume event
  849.  
  850.         BTST    #0,3+Message(A6)    ; test bit zero in low byte of Message
  851.         BNE.S    @1            ; this is a resume event
  852.         
  853.         MOVE.W    #True,G.InBackground    ; a suspend event
  854.         CLR.L    -(SP)            ; bug fix, was passing Message to DoActivate -JDR 2/27/89 
  855.         _FrontWindow            ; pass the front window to DoActivate -JDR 2/27/89
  856.         MOVE.W    #False,-(SP)        ; pass false to cause deactivate
  857.         BSR    DoActivate        ; go do the activate routine
  858.         BRA.S    Exit
  859.  
  860. @1        MOVE.W    #False,G.InBackground    ; a resume event
  861.         CLR.L    -(SP)            ; bug fix, was passing Message to DoActivate -JDR 2/27/89 
  862.         _FrontWindow            ; pass the front window to DoActivate -JDR 2/27/89
  863.         MOVE.W    #True,-(SP)        ; pass false to cause activate
  864.         BSR    DoActivate        ; go do the activate routine
  865.         
  866. Exit        
  867.         MOVEM.L    (SP)+,ModifyReg        ; restore this register after use
  868.         UNLK    A6
  869.         MOVEA.L    (SP)+,A0        ; save the caller's address
  870.         ADDA.L    #ParamSize,SP        ; strip the caller's parameters
  871.         JMP    (A0)
  872.  
  873.         DbgInfo    DoEvent            ; this name will appear in the debugger
  874.         ENDP
  875.         
  876. * ================================================
  877. * PROCEDURE EventLoop;
  878. * ================================================
  879. * Get the events by calling WaitNextEvent, if it's available, otherwise
  880. * by calling GetNextEvent. Also call AdjustCursor before doing the event.
  881. * After returning from handling the event, we have to make sure the cursor
  882. * is still adjusted proper ONLY because this application can "sleep" forever.
  883.  
  884. * An event record is allocated on the stack.  A pointer to this event is
  885. * passed to "DoEvent".  We loop until the user has selects "Quit" in the
  886. * file menu.  This program will exit through the DoMenuCommand routine.
  887.  
  888. * 1.02 made adjustments to the event loop logic.  There was a bug in calling
  889. * AdjustCursor at the wrong time. (it crashed under _GetNextEvent too!)
  890.  
  891. * If you are using modeless dialogs that have editText items,
  892. * you will want to call IsDialogEvent to give the caret a chance
  893. * to blink, even if WNE/GNE returned FALSE. However, check FrontWindow
  894. * for a non-NIL value before calling IsDialogEvent.
  895.  
  896.         SEG    'Main'            ; case sensitive
  897. EventLoop    PROC                ; any source file can use this routine
  898.  
  899. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  900. ParamBegin    EQU    *            ; start listing parameters here
  901. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  902. RetAddr     DS.L    1            ; place holder for return address
  903. A6Link        DS.L    1            ; place holder for A6 link
  904. TheEvent     DS    EventRecord         ; local copy of the event record
  905. MouseMvdRgn    DS.L    1            ; local region for MouseMoved events
  906. MousePos    DS.L    1            ; local point for mouse position
  907. LocalSize    EQU     *            ; size of all the local variables
  908.         ENDR
  909.         
  910.         IMPORT    AdjustCursor,GetGlobalMouse
  911.  
  912.         WITH    StackFrame        ; cover our local stack frame
  913.         LINK    A6,#LocalSize        ; allocate our local stack frame
  914.         
  915.         CLR.L    -(SP)
  916.         _NewRgn                ; create region for AdjustCursor
  917.         MOVE.L    (SP)+,MouseMvdRgn(A6)    ; save the handle to this region
  918.  
  919. * ------------- GET NEXT EVENT LOOP -------------
  920. NextEvent    
  921.         CMPI.W    #True,G.HasWNEvent     ; see if we can call WaitNextEvent
  922.         BNE.S    @1            ; nope, old time events
  923.         
  924.         PEA    MousePos(A6)        ; here's the mouse
  925.         BSR    GetGlobalMouse        ; get global coordinate
  926.         MOVE.L    MousePos(A6),-(SP)    ; here's the mouse
  927.         MOVE.L    MouseMvdRgn(A6),-(SP)    ; the region to change
  928.         BSR    AdjustCursor        ; adjust the cursor and region
  929.         CLR.W    -(SP)            ; space for result
  930.         MOVE.W    #EveryEvent,-(SP)    ; the events we want
  931.         PEA    TheEvent(A6)        ; pointer to the event record
  932.         MOVE.L    #SleepValue,-(SP)    ; the sleeping time value
  933.         MOVE.L    MouseMvdRgn(A6),-(SP)    ; the current MouseRgn
  934.         _WaitNextEvent
  935.         BRA.S    @2            ; got an event to handle?
  936.     
  937.                         ; no WaitNextEvent trap available
  938. @1        _SystemTask            ; call SystemTask for drivers and DAs
  939.         CLR.W    -(SP)            ; space for result
  940.         MOVE.W    #EveryEvent,-(SP)    ; the events we want
  941.         PEA    TheEvent(A6)        ; pass a pointer to our event
  942.         _GetNextEvent
  943. @2        MOVE.W    (SP)+,D0        ; result code
  944.         BEQ.S    NextEvent        ; no event, get another one
  945.         
  946. GotEvent    MOVE.L    TheEvent.where(A6),-(SP); the mouse location
  947.         MOVE.L    MouseMvdRgn(A6),-(SP)    ; the region to change
  948.         BSR    AdjustCursor        ; adjust cursor BEFORE doing event
  949.         PEA    TheEvent(A6)        ; pass the pointer to our event
  950.         BSR    DoEvent            ; do the event and return
  951.  
  952.         BRA.S    NextEvent        ; done with that event, get the next
  953.  
  954. Exit        UNLK    A6            ; destroy the link
  955.         MOVEA.L    (SP)+,A0        ; pull off the return address
  956.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  957.         JMP    (A0)            ; return to the caller
  958.  
  959.         DbgInfo    EvntLoop        ; this name will appear in the debugger
  960.         ENDP
  961.  
  962. * ================================================
  963. * --------------- MAIN ENTRY POINT ---------------
  964. * ================================================
  965. * This is the entry point of the program.  We start with data initializing
  966. * and then to get the System environment (SysEnvirons).  We unload the
  967. * initialization code segment and finally get started with the EventLoop.
  968.  
  969.         SEG    'Main'            ; case sensitive
  970. StartUp            MAIN                ; entry point of the program
  971.         
  972.         IMPORT    _DataInit,Initialize,    \
  973.             ForceEnvirons,EventLoop
  974.  
  975.         JSR    _DataInit        ; initialize those constants    
  976.         PEA    _DataInit        ; get rid of that segment
  977.         _UnloadSeg
  978.  
  979. * If you have stack requirements that differ from the default, then you could
  980. * use SetApplLimit to increase StackSpace at this point, before calling MaxApplZone.
  981.  
  982.         _MaxApplZone            ; result in D0
  983.         JSR    Initialize        ; get things the program set up
  984.         PEA    Initialize
  985.         _UnloadSeg            ; we're done this that segment too
  986.         LEA    EventLoop,A0        ; on your mark, get set,...
  987.         JMP    (A0)            ; go into the event loop
  988.         ENDP
  989.  
  990.         END                ; end of this source file
  991.  
  992.